package com.itc.bi.utils;

import com.itc.bi.config.MinioAPI;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

/**
 * @program: itc-airport-cloud
 * @description: mqtt回调
 * @author: songxiude
 * @create: 2024-07-15 15:20
 **/
public class SSLUtils {

    public static SSLSocketFactory getSingleSocketFactory(String caCrtFile) throws Exception {

        Security.addProvider(new BouncyCastleProvider());
        X509Certificate caCert = null;

        BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(Files.readAllBytes(Paths.get(caCrtFile))));
        //BufferedInputStream bis = new BufferedInputStream(caCrtFileInputStream);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        while (bis.available() > 0) {
            caCert = (X509Certificate) cf.generateCertificate(bis);
        }
        KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
        caKs.load(null, null);
        caKs.setCertificateEntry("cert-certificate", caCert);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(caKs);
        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, tmf.getTrustManagers(), null);
        return sslContext.getSocketFactory();
    }


//    public static SSLSocketFactory getSocketFactory(final String caCrtFile,
//                                                    final String crtFile, final String keyFile, final String password)
//            throws Exception {
//        Security.addProvider(new BouncyCastleProvider());
//
//        // load CA certificate
//        X509Certificate caCert = null;
//
//        FileInputStream fis = new FileInputStream(caCrtFile);
//        BufferedInputStream bis = new BufferedInputStream(fis);
//        CertificateFactory cf = CertificateFactory.getInstance("X.509");
//
//        while (bis.available() > 0) {
//            caCert = (X509Certificate) cf.generateCertificate(bis);
//        }
//
//        // load client certificate
//        bis = new BufferedInputStream(new FileInputStream(crtFile));
//        X509Certificate cert = null;
//        while (bis.available() > 0) {
//            cert = (X509Certificate) cf.generateCertificate(bis);
//        }
//
//        // load client private key
//        PEMParser pemParser = new PEMParser(new FileReader(keyFile));
//        Object object = pemParser.readObject();
//        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
//
//        PEMParser pemParser2 = new PEMParser(new FileReader("D:\\ceshi\\aaa.pem"));
//        Object object2 = pemParser2.readObject();
//
//        PEMKeyPair pemKeyPair  = new PEMKeyPair((SubjectPublicKeyInfo) object2, (PrivateKeyInfo) object);
//        KeyPair key = converter.getKeyPair(pemKeyPair);
//        pemParser.close();
//
//        // CA certificate is used to authenticate server
//        KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
//        caKs.load(null, null);
//        caKs.setCertificateEntry("ca-certificate", caCert);
//        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
//        tmf.init(caKs);
//
//        // client key and certificates are sent to server, so it can authenticate
//        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
//        ks.load(null, null);
//        ks.setCertificateEntry("certificate", cert);
//        ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(),
//                new java.security.cert.Certificate[]{cert});
//        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
//                .getDefaultAlgorithm());
//        kmf.init(ks, password.toCharArray());
//
//        // finally, create SSL socket factory
//        SSLContext context = SSLContext.getInstance("TLSv1.2");
//        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
//
//        return context.getSocketFactory();
//    }

    /**
     * 获取socket工厂类
     * @param caCrtFile
     * @param crtFile
     * @param keyFile
     * @param password
     * @return
     * @throws Exception
     */

    public static SSLSocketFactory getSSLSocketFactory(final InputStream caCrtFile, final InputStream crtFile, final InputStream keyFile, final String password) throws Exception {
        InputStream caInputStream = null;
        InputStream crtInputStream = null;
        InputStream keyInputStream = null;
        try {
            Security.addProvider(new BouncyCastleProvider());
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            //caInputStream = new ClassPathResource(caCrtFile).getInputStream();
            caInputStream = caCrtFile;
            //X509Certificate caCert = null;
            X509Certificate caCert = (X509Certificate) cf.generateCertificate(caInputStream);
//            while (caInputStream.available() > 0) {
//                caCert = (X509Certificate) cf.generateCertificate(caInputStream);
//            }
            //crtInputStream = new ClassPathResource(crtFile).getInputStream();
            crtInputStream = crtFile;
            //X509Certificate cert = null;
            X509Certificate cert = (X509Certificate) cf.generateCertificate(crtInputStream);
//            while (crtInputStream.available() > 0) {
//                cert = (X509Certificate) cf.generateCertificate(crtInputStream);
//            }
            //keyInputStream = new ClassPathResource(keyFile).getInputStream();
            keyInputStream = keyFile;
            PEMParser pemParser = new PEMParser(new InputStreamReader(keyInputStream));
            Object object = pemParser.readObject();
            PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
            KeyPair key;
            if (object instanceof PEMEncryptedKeyPair) {
                key = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
            } else {
                key = converter.getKeyPair((PEMKeyPair) object);
            }
            pemParser.close();
            KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
            caKs.load(null, null);
            caKs.setCertificateEntry("ca-certificate", caCert);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
            tmf.init(caKs);
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(null, null);
            ks.setCertificateEntry("certificate", cert);
            ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert});
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, password.toCharArray());
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            return context.getSocketFactory();
        }
        finally {
            if (null != caInputStream) {
                caInputStream.close();
            }
            if (null != crtInputStream) {
                crtInputStream.close();
            }
            if (null != keyInputStream) {
                keyInputStream.close();
            }
        }
    }

    /**
     * 获取socket工厂类
     * @param caCrtFile
     * @param crtFile
     * @param keyFile
     * @param password
     * @return
     * @throws Exception
     */

    public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception {
        InputStream caInputStream = null;
        InputStream crtInputStream = null;
        InputStream keyInputStream = null;
        try {
            Security.addProvider(new BouncyCastleProvider());
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            caInputStream = new ClassPathResource(caCrtFile).getInputStream();
            X509Certificate caCert = null;
            while (caInputStream.available() > 0) {
                caCert = (X509Certificate) cf.generateCertificate(caInputStream);
            }
            crtInputStream = new ClassPathResource(crtFile).getInputStream();
            X509Certificate cert = null;
            while (crtInputStream.available() > 0) {
                cert = (X509Certificate) cf.generateCertificate(crtInputStream);
            }
            keyInputStream = new ClassPathResource(keyFile).getInputStream();
            PEMParser pemParser = new PEMParser(new InputStreamReader(keyInputStream));
            Object object = pemParser.readObject();
            PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
            KeyPair key;
            if (object instanceof PEMEncryptedKeyPair) {
                key = converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv));
            } else {
                key = converter.getKeyPair((PEMKeyPair) object);
            }
            pemParser.close();
            KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
            caKs.load(null, null);
            caKs.setCertificateEntry("ca-certificate", caCert);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
            tmf.init(caKs);
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(null, null);
            ks.setCertificateEntry("certificate", cert);
            ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert});
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, password.toCharArray());
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            return context.getSocketFactory();
        }
        finally {
            if (null != caInputStream) {
                caInputStream.close();
            }
            if (null != crtInputStream) {
                crtInputStream.close();
            }
            if (null != keyInputStream) {
                keyInputStream.close();
            }
        }
    }


    public static SSLSocketFactory getSSL(String caFilePath,String certFilePath,String keyFilePath,String password){
        // 加载CA证书
        try {
            // 加载CA证书
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            FileInputStream caInputStream = new FileInputStream("D:\\ceshi\\caCert.pem");
            X509Certificate caCert = (X509Certificate) cf.generateCertificate(caInputStream);
            caInputStream.close();

            // 创建并初始化 TrustStore
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);
            trustStore.setCertificateEntry("ca-cert", caCert);

            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(trustStore);

            // 加载客户端证书
            FileInputStream certInputStream = new FileInputStream("D:\\ceshi\\cert.txt");
            X509Certificate clientCert = (X509Certificate) cf.generateCertificate(certInputStream);
            certInputStream.close();

            // 加载客户端私钥
            String key = new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get("D:\\ceshi\\keys.txt")))
                    .replaceAll("-----\\w+ PRIVATE KEY-----", "").replaceAll("\\s", "");
            byte[] decodedKey = Base64.getDecoder().decode(key);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

            // 创建并初始化 KeyStore
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            keyStore.setKeyEntry("client-key", privateKey, password.toCharArray(), new java.security.cert.Certificate[]{clientCert});

            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(keyStore, password.toCharArray());

            // 配置SSL上下文
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new java.security.SecureRandom());
            return sslContext.getSocketFactory();
        }catch (Exception e){

        }
        return null;
    }

}

